﻿using System.Globalization;
using System.Linq;
using Fuse8.DomainFramework.BusinessService;
using Fuse8.DomainFramework.Common.Locator;
using Fuse8.DomainFramework.DataAccess.InMemoryDatabase;
using Fuse8.GlobalizationFramework.BusinessServices;
using Fuse8.GlobalizationFramework.Domain;
using Fuse8.GlobalizationFramework.Domain.Commands;
using Fuse8.GlobalizationFramework.Infrastructure;
using Microsoft.Practices.Unity;
using Moq;
using NUnit.Framework;

namespace UnitTests
{
    [TestFixture]
    public class AdminResourseServiceTests
    {
        [SetUp]
        public void SetUp()
        {
            IUnityContainer container = new UnityContainer();
            var locator = new UnityServiceLocatorWithLazy(container);
            DependencyServiceLocator.SetLocatorProvider(() => locator);

            var entityDataRepository = InMemoryDataRepositoryConfiguration<Resource, int>.CreateRepository();
            entityDataRepository.Add(new Resource()
            {
                Key = "Key1",
                Value = "Value1",
                Locale = "fr-FR"
            });
            entityDataRepository.Add(new Resource()
            {
                Key = "Key2",
                Value = "Value2",
                Locale = "fr-FR"
            });
            entityDataRepository.Add(new Resource()
            {
                Key = "Key1",
                Value = "en1",
                Locale = "en-GB"
            });
            entityDataRepository.Add(new Resource()
            {
                Key = "Key2",
                Value = "en2",
                Locale = "en-GB"
            });
            entityDataRepository.Add(new Resource()
            {
                Key = "Key3",
                Value = "en3",
                Locale = "en-GB"
            });
            container.RegisterInstance(entityDataRepository);
            var factory = new Mock<IResourceCommandFactory>();
            factory.Setup(p => p.GetCommand<ResourceSelectAllByLocale>()).Returns(
                new ResourceSelectAllByLocaleInMemoryCommand());

            var settings = new Mock<IGlobalizationSetting>();
            settings.Setup(p => p.CurrentCulture).Returns(new CultureInfo("fr-FR"));
            settings.Setup(p => p.DefaultCulture).Returns(new CultureInfo("en-GB"));
            container.RegisterInstance(settings.Object);
            container.RegisterInstance(factory.Object);
        }

        [Test]
        public void FindAll_AppendDefaultFalse_GetsOnlyInNeededLocale()
        {
            var list = AdminResourceService.FindAll(false);
            Assert.AreEqual(2, list.Count(), "Should be 2 items");
            Assert.IsTrue(list.FirstOrDefault(p => p.Key == "Key1").Translated);
            Assert.IsTrue(list.FirstOrDefault(p => p.Key == "Key2").Translated);
        }

        [Test]
        public void FindAll_AppendDefaultTrue_GetsInNeededLocaleAndDefault()
        {
            var list = AdminResourceService.FindAll(true);
            Assert.AreEqual(3, list.Count(), "Should be 3 items");
            Assert.IsTrue(list.FirstOrDefault(p => p.Key == "Key1").Translated);
            Assert.IsTrue(list.FirstOrDefault(p => p.Key == "Key2").Translated);
            Assert.IsFalse(list.FirstOrDefault(p => p.Key == "Key3").Translated);
        } 
    }

    public class ResourceSelectAllByLocaleInMemoryCommand : ResourceSelectAllByLocale
    {
        public override System.Linq.IQueryable<Resource> Execute()
        {
            var service = new BusinessServiceFacade<Resource, int>();
            if (!AppendDefault)
            {
                return service.Find(p => p.Locale == Locale).Select(p=> new Resource(){Locale = p.Locale, Key = p.Key, Value = p.Value, Id = p.Id, Translated = true}).AsQueryable();
            }
            var list = service.Find(p => p.Locale == Locale).Select(p => new Resource() { Locale = p.Locale, Key = p.Key, Value = p.Value, Id = p.Id, Translated = true }).ToList();
            list.AddRange(
                service.Find(p => p.Locale == DefaultLocale && !list.Any(c => c.Key == p.Key)).Select(
                    p => new Resource() {Locale = p.Locale, Key = p.Key, Value = p.Value, Id = p.Id, Translated = false}));
            return list.AsQueryable();
        }
    }
}
